package com.ccb.sc.member.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
//psl import com.ccb.sc.common.bind.exception.BizException;
import com.ccb.sc.common.code.BizCodeFace;
import com.ccb.sc.common.code.ErrorCode;
import com.ccb.sc.common.modules.member.entity.SignIn;
import com.ccb.sc.common.modules.member.enums.MemberPointsLogType;
import com.ccb.sc.common.modules.member.mapper.SignInMapper;
import com.ccb.sc.common.modules.member.service.MemberPointsService;
import com.ccb.sc.common.modules.message.enums.MessageType;
import com.ccb.sc.common.modules.message.service.MessageService;
import com.ccb.sc.common.modules.setting.service.ISettingsService;
import com.ccb.sc.common.modules.setting.vo.SignInSettingsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 签到表 服务实现类
 * </p>
 *
 * @author ken
 * @since 2020-09-29
 */
@Service
public class SignInService extends ServiceImpl<SignInMapper, SignIn> {

    private ISettingsService settingsService;

    private MemberPointsService memberPointsService;

    private MessageService messageService;

    public List<LocalDate> findAllSignInList(Long memberId) {
        /*LocalDate now = LocalDate.now();
        // 获取当前月的第一天
        LocalDate firstDay = now.with(TemporalAdjusters.firstDayOfMonth());
        // 获取当前月的最后一天
        LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth());
        List<SignIn> list = this.list(new QueryWrapper<SignIn>().lambda()
                .eq(SignIn::getMemberId, memberId)
                .gt(SignIn::getSignDate, firstDay)
                .lt(SignIn::getSignDate, lastDay));
        Set<LocalDate> signSet = list.stream().map(SignIn::getSignDate).collect(Collectors.toSet());
        List<MonthSignInListVo> monthSignInList = new ArrayList<>();
        // 构造当月每天签到数据
        while (firstDay.compareTo(lastDay) <= 0) {
            MonthSignInListVo listVo = new MonthSignInListVo();
            LocalDate date = firstDay;
            listVo.setDate(date);
            listVo.setSign(signSet.contains(date));
            monthSignInList.add(listVo);
            firstDay = firstDay.plusDays(1);
        }
        return monthSignInList;*/
        LocalDate date = LocalDate.now();
        // 获取当前月的第一天
        LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
        List<SignIn> list = this.list(new QueryWrapper<SignIn>().lambda()
                .eq(SignIn::getMemberId, memberId)
                .ge(SignIn::getSignDate, firstDay)
                .orderByDesc(SignIn::getSignDate));
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().map(SignIn::getSignDate).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    public int sign(Long memberId) {
        LocalDate date = LocalDate.now();
        // 获取当前月的第一天
        LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
        SignIn lastSignIn = this.getOne(Wrappers.<SignIn>lambdaQuery()
                .eq(SignIn::getMemberId, memberId)
                .gt(SignIn::getSignDate, firstDay)
                .orderByDesc(SignIn::getSignDate)
                .last("limit 1"));
        if (lastSignIn != null && lastSignIn.getSignDate().compareTo(date) == 0) {
            //psl throw new BizException(BizCodeFace.createBizCode(ErrorCode.DATE_NULL).message("今天已签到，请勿重复签到"));
        }
        int cumulativeDays = lastSignIn == null ? 1 : lastSignIn.getCumulativeDays() + 1;
        SignIn signIn = new SignIn();
        signIn.setMemberId(memberId);
        signIn.setSignDate(date);
        signIn.setCumulativeDays(cumulativeDays);
        boolean result = this.save(signIn);
        if (!result) {
            //psl throw new BizException(BizCodeFace.createBizCode(ErrorCode.FAIL));
        }

        // 奖励积分
        SignInSettingsVo signInSettingsVo = this.settingsService.getSettings(SignInSettingsVo.class);
        this.memberPointsService.award(memberId, signInSettingsVo.getRewardEveryday(), MemberPointsLogType.SIGN_IN, String.valueOf(signIn.getId()));
        int reward = signInSettingsVo.getRewardEveryday();
        // 增加消息通知
        String messageBody = String.format("恭喜您通过每日签到获得%d积分", reward);
        this.messageService.create(memberId, MessageType.POINTS, MessageType.POINTS.getDesc(), messageBody);
        if (cumulativeDays == 7) {
            this.memberPointsService.award(memberId, signInSettingsVo.getRewardSevenDays(), MemberPointsLogType.REWARD_SEVEN_DAYS, String.valueOf(signIn.getId()));
            messageBody = String.format("恭喜您通过累计签到7天额外获得%d积分", signInSettingsVo.getRewardSevenDays());
            this.messageService.create(memberId, MessageType.POINTS, MessageType.POINTS.getDesc(), messageBody);
            reward += signInSettingsVo.getRewardSevenDays();
        } else if (cumulativeDays == 17) {
            this.memberPointsService.award(memberId, signInSettingsVo.getRewardSeventeenDays(), MemberPointsLogType.REWARD_SEVENTEEN_DAYS, String.valueOf(signIn.getId()));
            messageBody = String.format("恭喜您通过累计签到17天额外获得%d积分", signInSettingsVo.getRewardSeventeenDays());
            this.messageService.create(memberId, MessageType.POINTS, MessageType.POINTS.getDesc(), messageBody);
            reward += signInSettingsVo.getRewardSeventeenDays();
        } else if (cumulativeDays == 27) {
            this.memberPointsService.award(memberId, signInSettingsVo.getRewardTwentySevenDays(), MemberPointsLogType.REWARD_TWENTY_SEVEN_DAYS, String.valueOf(signIn.getId()));
            messageBody = String.format("恭喜您通过累计签到27天额外获得%d积分", signInSettingsVo.getRewardTwentySevenDays());
            this.messageService.create(memberId, MessageType.POINTS, MessageType.POINTS.getDesc(), messageBody);
            reward += signInSettingsVo.getRewardTwentySevenDays();
        }
        return reward;
    }

    public boolean isSignIn(Long memberId) {
        LocalDate now = LocalDate.now();
        return this.count(Wrappers.<SignIn>lambdaQuery().eq(SignIn::getMemberId, memberId).eq(SignIn::getSignDate, now)) > 0;
    }

    @Autowired
    public void setSettingsService(ISettingsService settingsService) {
        this.settingsService = settingsService;
    }

    @Autowired
    public void setMemberPointsService(MemberPointsService memberPointsService) {
        this.memberPointsService = memberPointsService;
    }

    @Autowired
    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }
}
